package com.client;

import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.http.client.URL;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DecoratorPanel;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.datepicker.client.DateBox;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.Query;
import com.google.gwt.visualization.client.QueryResponse;
import com.google.gwt.visualization.client.Query.Callback;

public class PLSearch extends SlidePanel {
	public DecoratorPanel dplSearch;
	public FlexTable ftSearch;
	public FlowPanel hpTags;
	public HTML hSearchHint;
	public Button btnSearch;
	public DisclosurePanel plAdv;
	public FlexTable gAdvSearch;
	public FlowPanel fpTags;
	public HorizontalPanel hpNavi;
	public Button btnPrev;
	public Button btnNext;
	public TextBox tbTag;
	public Button btnReset;
	public DateBox dbBegin = null;
	public DateBox dbEnd = null;
	public TextBox tbDfmt = null;
	public TextBox tbX = null;
	public TextBox tbY = null;

	public String prev = "";
	public String next = "";

	protected void onFirstShow() {
		this.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		this.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);

		dplSearch = new DecoratorPanel();
		ftSearch = new FlexTable();

		hpTags = new FlowPanel();
		hpTags.setStyleName("appTagSelected");
		hSearchHint = new HTML(CNStatsFront.get().constants.searchHint());
		btnSearch = new Button(CNStatsFront.get().constants.search(),
				new ClkSearch());

		fpTags = new FlowPanel();
		fpTags.setStyleName("appTagList");
		hpNavi = new HorizontalPanel();
		hpNavi.setStyleName("appNavi");
		hpNavi.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
		hpNavi.setSpacing(2);
		btnPrev = new Button();
		btnNext = new Button();
		btnPrev.setText("<");
		btnNext.setText(">");
		btnPrev.addClickHandler(new ClkNav("prev"));
		btnNext.addClickHandler(new ClkNav("next"));
		btnPrev.setEnabled(false);
		btnNext.setEnabled(false);
		tbTag = new TextBox();
		tbTag.addFocusHandler(new FocusHandler() {
			public void onFocus(FocusEvent event) {
				tbTag.setText("");
			}
		});
		tbTag.addBlurHandler(new BlurHandler() {
			public void onBlur(BlurEvent event) {
				tbTag.setText(CNStatsFront.get().constants.searchTag());
			}
		});
		tbTag.addKeyPressHandler(new KeyPressHandler() {
			public void onKeyPress(KeyPressEvent event) {
				// Get return key
				if (tbTag.getText().length() > 0 && 13 == event.getCharCode()) {
					Tag tag = new Tag();
					tag.setText(tbTag.getText());
					tag.addClickHandler(new ClkRemoveTag());
					CNStatsFront.get().plSearch.hpTags.remove(
							CNStatsFront.get().plSearch.hSearchHint);
					CNStatsFront.get().plSearch.hpTags.add(tag);
					CNStatsFront.get().plSearch.getTags();
					tbTag.setText("");
					tbTag.setFocus(true);
				}
			}
		});
		tbTag.setText(CNStatsFront.get().constants.searchTag());
		btnReset = new Button(CNStatsFront.get().constants.reset(), new ClkReset());
		
		hpNavi.add(btnPrev);
		hpNavi.add(btnNext);
		hpNavi.add(tbTag);
		hpNavi.add(btnReset);

		plAdv = new DisclosurePanel(CNStatsFront.get().constants.advanced());
		plAdv.addOpenHandler(new OpenHandlerAdv());

		this.add(dplSearch);
		dplSearch.add(ftSearch);
		ftSearch.setWidget(0, 0, hpTags);
		ftSearch.setWidget(0, 1, btnSearch);
		ftSearch.getFlexCellFormatter().setHorizontalAlignment(0, 1,
				HasHorizontalAlignment.ALIGN_RIGHT);
		ftSearch.getFlexCellFormatter().setColSpan(1, 0, 2);
		ftSearch.setWidget(1, 0, fpTags);
		ftSearch.getFlexCellFormatter().setColSpan(2, 0, 2);
		ftSearch.setWidget(2, 0, hpNavi);
		ftSearch.getFlexCellFormatter().setColSpan(3, 0, 2);
		ftSearch.setWidget(3, 0, plAdv);
		this.reset();

//		Query.create(CNStatsFront.baseURL + "queryhistory").send(
//				new CBQueryHistory());
	}

	public void getTags() {
		fpTags.clear();
		fpTags.add(new InlineLabel(CNStatsFront.get().constants.relatedTags()));
		fpTags.add(new InlineLabel(CNStatsFront.get().constants.loading()));
		prev = "";
		next = "";
		btnPrev.setEnabled(false);
		btnNext.setEnabled(false);
		String searchURL;
		if (this.getTagsText().equals("")) {
			searchURL = CNStatsFront.baseURL + "querytags?direction=next";
		} else {
			searchURL = CNStatsFront.baseURL + "querytags?direction=related&tag="
					+ this.getTagsText();
		}

		Query.create(URL.encode(searchURL)).send(new CBQueryTags());
	}

	public String getTagsText() {
		if (this.hpTags.getWidgetIndex(hSearchHint) >= 0
				|| 0 == this.hpTags.getWidgetCount())
			return "";
		String text = "";
		for (int i = 0; i < this.hpTags.getWidgetCount(); i++) {
			if (i > 0)
				text += " ";
			text += ((Tag) (this.hpTags.getWidget(i))).getText();
		}
		return text;
	}

	public void reset() {
		hpTags.clear();
		hpTags.add(hSearchHint);
		fpTags.clear();
		fpTags.add(new InlineLabel(CNStatsFront.get().constants.relatedTags()));
		fpTags.add(new InlineLabel(CNStatsFront.get().constants.loading()));
		plAdv.setOpen(false);

		Query.create(CNStatsFront.baseURL + "querytags?direction=next").send(
				new CBQueryTags());
		
		//TODO: Reset advanced options
	}
}

final class OpenHandlerAdv implements OpenHandler<DisclosurePanel> {
	public void onOpen(OpenEvent<DisclosurePanel> event) {
		if (null == CNStatsFront.get().plSearch.plAdv.getContent()) {
			CNStatsFront.get().plSearch.gAdvSearch = new FlexTable();
			CNStatsFront.get().plSearch.dbBegin = new DateBox();
			CNStatsFront.get().plSearch.dbEnd = new DateBox();
			CNStatsFront.get().plSearch.tbDfmt = new TextBox();
			CNStatsFront.get().plSearch.tbX = new TextBox();
			CNStatsFront.get().plSearch.tbY = new TextBox();


//			CNStatsFront.get().plSearch.ftSearch.setBorderWidth(2);
//			CNStatsFront.get().plSearch.gAdvSearch.setBorderWidth(2);

			CNStatsFront.get().plSearch.gAdvSearch.setHTML(0, 0,
					CNStatsFront.get().constants.begin());
			CNStatsFront.get().plSearch.gAdvSearch.setWidget(0, 1,
					CNStatsFront.get().plSearch.dbBegin);
			CNStatsFront.get().plSearch.gAdvSearch.setHTML(1, 0,
					CNStatsFront.get().constants.end());
			CNStatsFront.get().plSearch.gAdvSearch.setWidget(1, 1,
					CNStatsFront.get().plSearch.dbEnd);
			CNStatsFront.get().plSearch.gAdvSearch.setHTML(2, 0,
					CNStatsFront.get().constants.format());
			CNStatsFront.get().plSearch.gAdvSearch.setWidget(2, 1,
					CNStatsFront.get().plSearch.tbDfmt);
			CNStatsFront.get().plSearch.gAdvSearch.setHTML(3, 0,
					CNStatsFront.get().constants.x());
			CNStatsFront.get().plSearch.gAdvSearch.setWidget(3, 1,
					CNStatsFront.get().plSearch.tbX);
			CNStatsFront.get().plSearch.gAdvSearch.setHTML(4, 0,
					CNStatsFront.get().constants.y());
			CNStatsFront.get().plSearch.gAdvSearch.setWidget(4, 1,
					CNStatsFront.get().plSearch.tbY);
			
			CNStatsFront.get().plSearch.gAdvSearch.getCellFormatter()
					.setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_RIGHT);
			CNStatsFront.get().plSearch.gAdvSearch.getCellFormatter()
					.setHorizontalAlignment(1, 0, HasHorizontalAlignment.ALIGN_RIGHT);
			CNStatsFront.get().plSearch.gAdvSearch.getCellFormatter()
					.setHorizontalAlignment(2, 0, HasHorizontalAlignment.ALIGN_RIGHT);
			CNStatsFront.get().plSearch.gAdvSearch.getCellFormatter()
					.setHorizontalAlignment(3, 0, HasHorizontalAlignment.ALIGN_RIGHT);
			CNStatsFront.get().plSearch.gAdvSearch.getCellFormatter()
					.setHorizontalAlignment(4, 0, HasHorizontalAlignment.ALIGN_RIGHT);

			CNStatsFront.get().plSearch.plAdv
					.setContent(CNStatsFront.get().plSearch.gAdvSearch);
			CNStatsFront.get().plSearch.plAdv.setAnimationEnabled(true);
		}
	}
}

final class ClkSearch implements ClickHandler {
	public void onClick(ClickEvent event) {
		String tags = CNStatsFront.get().plSearch.getTagsText();
		if (tags.equals(""))
			return;
		String searchURL = CNStatsFront.baseURL + "querystats?tags="
				+ CNStatsFront.get().plSearch.getTagsText();

		DateTimeFormat dfmt = DateTimeFormat.getFormat("yyyyMMddHHmmss");
		if (null != CNStatsFront.get().plSearch.dbBegin
				&& null != CNStatsFront.get().plSearch.dbBegin.getValue()) {
			searchURL += "&begin="
					+ dfmt.format(CNStatsFront.get().plSearch.dbBegin.getValue());
		}
		if (null != CNStatsFront.get().plSearch.dbEnd
				&& null != CNStatsFront.get().plSearch.dbEnd.getValue()) {
			searchURL += "&end="
					+ dfmt.format(CNStatsFront.get().plSearch.dbEnd.getValue());
		}
		if (null != CNStatsFront.get().plSearch.tbDfmt
				&& CNStatsFront.get().plSearch.tbDfmt.getValue().length() > 0) {
			searchURL += "&dfmt=" + CNStatsFront.get().plSearch.tbDfmt.getValue();
		}
		if (null != CNStatsFront.get().plSearch.tbX
				&& CNStatsFront.get().plSearch.tbX.getValue().length() > 0) {
			searchURL += "&x=" + CNStatsFront.get().plSearch.tbX.getValue();
		}
		if (null != CNStatsFront.get().plSearch.tbY
				&& CNStatsFront.get().plSearch.tbY.getValue().length() > 0) {
			searchURL += "&y=" + CNStatsFront.get().plSearch.tbY.getValue();
		}

		Query.create(URL.encode(searchURL)).send(new CBQueryStats());
	}
}

final class CBQueryStats implements Callback {
	public void onResponse(QueryResponse response) {
		if (response.isError()) {
			DialogInfo.info(CNStatsFront.get().constants.information(), response
					.getMessage()
					+ ":" + response.getDetailedMessage());
		} else {
			// Get the data from the QueryResponse.
			DataTable data = response.getDataTable();
			CNStatsFront.get().plCharts.setData(data);
			CNStatsFront.get().plCharts.show();
			CNStatsFront.get().plCharts.draw();
		}
	}
}

// final class CBQueryHistory implements Callback {
// public void onResponse(QueryResponse response) {
// if (response.isError()) {
// // TODO: Don't need pop up message.
// return;
// } else {
// DataTable data = response.getDataTable();
//
// MultiWordSuggestOracle oracle = (MultiWordSuggestOracle) CNStatsFront
// .get().plSearch.sbTags.getSuggestOracle();
// for (int i = 0; i < data.getNumberOfRows(); i++) {
// oracle.add(data.getValueString(i, 0));
// }
// }
// }
// }

final class CBQueryTags implements Callback {
	public void onResponse(QueryResponse response) {
		if (response.isError()) {
			// TODO: Don't need pop up message.
			return;
		} else {
			// Get the data from the QueryResponse.
			DataTable data = response.getDataTable();

			CNStatsFront.get().plSearch.fpTags.clear();
			CNStatsFront.get().plSearch.fpTags.add(new InlineLabel(
					CNStatsFront.get().constants.relatedTags()));
			if (0 == data.getNumberOfRows()) {
				CNStatsFront.get().plSearch.fpTags.add(new InlineLabel(
						CNStatsFront.get().constants.noMoreTags()));
				return;
			}
			for (int i = 0; i < data.getNumberOfRows(); i++) {
				//TODO: Use Tag factory with pagesize instances
				Tag tag = new Tag();
				tag.setText(data.getValueString(i, 0));
				tag.addClickHandler(new ClkAddTag());
				CNStatsFront.get().plSearch.fpTags.add(tag);
				if (data.getValueString(i, 2).equals("prev")) {
					CNStatsFront.get().plSearch.prev = data.getValueString(i, 0);
					CNStatsFront.get().plSearch.btnPrev.setEnabled(true);
				} else if (data.getValueString(i, 2).equals("next")) {
					CNStatsFront.get().plSearch.next = data.getValueString(i, 0);
					CNStatsFront.get().plSearch.btnNext.setEnabled(true);
				}
			}
		}
	}
}

final class ClkNav implements ClickHandler {
	private String direction;

	public ClkNav(String direction) {
		super();
		this.direction = direction;
	}

	public void onClick(ClickEvent event) {
		if ((0 == CNStatsFront.get().plSearch.prev.length() && direction
				.equals("prev"))
				|| (0 == CNStatsFront.get().plSearch.next.length() && direction
						.equals("next")))
			return;
		String searchURL = "";
		if (direction.equals("next"))
			searchURL = CNStatsFront.baseURL + "querytags?direction="
					+ this.direction + "&tag=" + CNStatsFront.get().plSearch.next;
		else if (direction.equals("prev"))
			searchURL = CNStatsFront.baseURL + "querytags?direction="
					+ this.direction + "&tag=" + CNStatsFront.get().plSearch.prev;
		Query.create(URL.encode(searchURL)).send(new CBQueryTags());
		CNStatsFront.get().plSearch.prev = "";
		CNStatsFront.get().plSearch.next = "";
		CNStatsFront.get().plSearch.btnPrev.setEnabled(false);
		CNStatsFront.get().plSearch.btnNext.setEnabled(false);
		CNStatsFront.get().plSearch.fpTags.clear();
		CNStatsFront.get().plSearch.fpTags.add(new InlineLabel(
				CNStatsFront.get().constants.relatedTags()));
		CNStatsFront.get().plSearch.fpTags.add(new InlineLabel(
				CNStatsFront.get().constants.loading()));
	}
}

final class ClkReset implements ClickHandler {
	public void onClick(ClickEvent event) {
		CNStatsFront.get().plSearch.reset();
	}
}
